#include "parse.h"
#define BUF_SIZE 9999

/**
* Given a char buffer returns the parsed request headers
*/
/*
parse解析HTTP请求数据，提取请求头部和其他相关信息。
若解析成功则返回包含请求信息的Request对象；
解析失败则打印错误信息并返回NULL
*/
Request *parse(char *buffer, int size, int socketFd)
{
	//Differant states in the state machine
	enum
	{
		STATE_START = 0,
		STATE_CR,
		STATE_CRLF,
		STATE_CRLFCR,
		STATE_CRLFCRLF
	};

	int i = 0, state;
	size_t offset = 0;
	char ch;
	char buf[BUF_SIZE];
	memset(buf, 0, BUF_SIZE);

	int crlf_num = 0;
	int headers_num=0;

	state = STATE_START;
	while (state != STATE_CRLFCRLF)
	{
		char expected = 0;

		if (i == size)
			break;
		if(i==8192){
			YY_BUFFER_STATE bufferstate = yy_create_buffer(NULL, 16384);
			yy_switch_to_buffer(bufferstate);
			printf("Request header out of buffer\n");
			return NULL;
		}

		ch = buffer[i++];
		buf[offset++] = ch;

		switch (state)
		{
		case STATE_START:
		case STATE_CRLF:
			expected = '\r';
			break;
		case STATE_CR:
		case STATE_CRLFCR:
			crlf_num += 1;
			expected = '\n';
			break;
		default:
			state = STATE_START;
			continue;
		}

		if (ch == expected)
			state++;
		else
			state = STATE_START;
	}

	//Valid End State
	if (state == STATE_CRLFCRLF)
	{
		Request *request = (Request *)malloc(sizeof(Request));
		request->header_count = 0;
		request->content_length=0;
		request->headers=NULL;
		request->message_body=NULL;
		//FINISHED TODO You will need to handle resizing this in parser.y
		if(crlf_num-2<=0)
			headers_num=0;
		else
			headers_num=crlf_num-2;
		request->headers = (Request_header *)malloc(sizeof(Request_header) * headers_num);
		set_parsing_options(buf, i, request);

		if (yyparse() == SUCCESS)
		{
			if(request->content_length>0)
				memcpy(request->message_body,buffer+offset,request->content_length);
			yylex_destroy();
			return request;
		}
	}
	//TODO Handle Malformed Requests
	//YY_BUFFER_STATE bufferstate = yy_create_buffer(NULL, 16384);
	//yy_switch_to_buffer(bufferstate);
	
	//while(yyparse());
	yylex_destroy();
	printf("Parsing Failed\n");
	return NULL;
}

void free_request(Request* request){
	if (request->headers!=NULL)
		free(request->headers);
	if (request->message_body!=NULL)
		free(request->message_body);
	free(request);
}